package com.clw.service.impl;

import com.clw.dataobject.Product;
import com.clw.dataobject.Return;
import com.clw.dataobject.ReturnDetail;
import com.clw.dto.ReturnDTO;
import com.clw.enums.ResultEnum;
import com.clw.exception.SellException;
import com.clw.repository.ProductRepository;
import com.clw.repository.ReturnDetailRepository;
import com.clw.repository.ReturnRepository;
import com.clw.service.ReturnService;
import com.clw.utils.DateUtils;
import com.clw.utils.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by Administrator on 2018-03-01.
 */
@Service
public class ReturnServiceImpl implements ReturnService{

    @Autowired
    private ReturnRepository repository;

    @Autowired
    private ReturnDetailRepository detailRepository;

    @Autowired
    private ProductRepository productRepository;

    @Override
    public Page<Return> findPage(String returnNo,  String startTime, String endTime, Pageable pageable) {
        return repository.findAll(getSpecification(returnNo,startTime,endTime),pageable);
    }

    @Override
    public Long getSize(String returnNo, String startTime, String endTime) {
        return repository.count(getSpecification(returnNo,startTime,endTime));
    }

    @Override
    public List<ReturnDetail> getDetail(String returnNo) {
        return detailRepository.findAllByReturnNo(returnNo);
    }

    @Override
    public Return findOne(Integer id) {
        return repository.findOne(id);
    }

    @Transactional
    @Override
    public ReturnDTO add(ReturnDTO dto) {
        Return return1=new Return();
        BeanUtils.copyProperties(dto,return1);
        return1.setCreateTime(new Date());
        return1.setStatus(0);
        Return result=repository.save(return1);
        for (ReturnDetail detail:dto.getDetails()){
            detail.setReturnNo(result.getReturnNo());
            detailRepository.save(detail);
        }
        return dto;
    }

    @Transactional
    @Override
    public ReturnDTO update(ReturnDTO dto) {
        List<ReturnDetail> oldValueList=detailRepository.findAllByReturnNo(dto.getReturnNo());
        List<ReturnDetail> newValueList=dto.getDetails();
        if (newValueList!=null&&newValueList.size()>0){
            for (ReturnDetail oldValue:oldValueList){
                boolean isUpdate=false;
                for (ReturnDetail newValue:newValueList){
                    if (oldValue.getId().equals(newValue.getId())){
                        newValue.setReturnNo(oldValue.getReturnNo());
                        detailRepository.save(newValue);
                        isUpdate=true;
                        break;
                    }
                }
                if (!isUpdate){
                    detailRepository.delete(oldValue);
                }
            }

            for (ReturnDetail value:newValueList){
                if (StringUtils.isEmpty(value.getId())){
                    value.setReturnNo(dto.getReturnNo());
                    detailRepository.save(value);
                }
            }

        }
        Return order=repository.findOne(dto.getId());
        BeanUtils.copyProperties(dto,order);
        repository.save(order);
        return dto;
    }

    @Transactional
    @Override
    public Return del(Return return1) {
        String returnNo=return1.getReturnNo();
        List<ReturnDetail> details=detailRepository.findAllByReturnNo(returnNo);
        repository.delete(return1);
        for (ReturnDetail detail:details){
            detailRepository.delete(detail);
        }
        return return1;
    }

    @Override
    public Return save(Return order) {
        return repository.save(order);
    }

    @Transactional
    @Override
    public Return review(Return order) {
        //查询订单明细
        String purNo=order.getReturnNo();
        List<ReturnDetail> detailList=detailRepository.findAllByReturnNo(purNo);
        //寻找对应商品
        for (ReturnDetail detail:detailList){
            Product product=productRepository.findOne(detail.getProductId());
            if (product==null){
                throw new SellException(ResultEnum.PRODUCT_NOT_FOUND);
            }
            Integer count=product.getCount()-detail.getCount();
            if (count<0){
                throw new SellException(ResultEnum.STOCK_NOT_ENOUGH);
            }
            product.setCount(count);
        }
        return repository.save(order);

    }

    private Specification<Return> getSpecification(String returnNo,  String startTime, String endTime){
        return new Specification<Return>() {
            @Override
            public Predicate toPredicate(Root<Return> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates=new ArrayList<>();
                if (StringUtils.isNotEmpty(returnNo)){
                    predicates.add(criteriaBuilder.like(root.get("returnNo"),"%"+returnNo+"%"));
                }
                if (StringUtils.isNotEmpty(startTime)){
                    Date start= DateUtils.stringToDate(startTime);
                    predicates.add(criteriaBuilder.greaterThan(root.get("createTime"),start));
                }
                if (StringUtils.isNotEmpty(endTime)){
                    Date end=DateUtils.addDay(endTime,1);
                    predicates.add(criteriaBuilder.lessThan(root.get("createTime"),end));
                }
                return criteriaQuery.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
            }
        };
    }
}
